package com.lab.network.proxy;

import android.text.TextUtils;

import com.cuitrip.apiservice.BusinessHelper;
import com.cuitrip.app.MainApplication;
import com.cuitrip.service.BuildConfig;
import com.lab.logtrack.AppLog;
import com.lab.network.config.CachePolicyEnum;
import com.lab.network.model.CtApiRequest;
import com.lab.network.model.CtApiResponse;
import com.lab.network.model.CtRemoteBusiness;
import com.lab.network.model.IProxyCallback;
import com.lab.network.model.ParseType;
import com.lab.network.model.ProxyResult;
import com.lab.network.model.ResultCallback;
import com.lab.tools.ui.HttpLog;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by ak on 15/11/16.
 */
public class ApiProxy extends Proxy {

    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    public static final String PROXY_NAME = "ApiProxy";
    public static final int APIPROXY_TYPE_RESPONSE = 0x10000001;
    private OkHttpClient mOkHttpClient;
    private boolean shouldResponseOnUiThread = true;
    private boolean asyncExecute = true;
    public static LinkedList<HttpLog> httpLogList = new LinkedList<>();

    public ApiProxy() {
        initClient();
    }


    public ApiProxy(IProxyCallback proxyCallback) {
        super(proxyCallback);
        initClient();
    }

    private void initClient(){
        OkHttpClient defaultClient = new OkHttpClient();
        OkHttpClient.Builder builder = defaultClient.newBuilder()
                .connectTimeout(65, TimeUnit.SECONDS)
                .writeTimeout(65, TimeUnit.SECONDS)
                .readTimeout(65, TimeUnit.SECONDS);
        if (!TextUtils.isEmpty(MainApplication.getInstance().getCachePath())) {
            int cacheSize = 50 * 1024 * 1024; // 50 MiB
            Cache cache = new Cache(new File(MainApplication.getInstance().getCachePath()), cacheSize);
            builder.cache(cache);
        }
        mOkHttpClient = builder.build();
    }


    public void setShouldResponseOnUiThread(boolean shouldResponseOnUiThread) {
        this.shouldResponseOnUiThread = shouldResponseOnUiThread;
    }

    public void setAsyncExecute(boolean asyncExecute) {
        this.asyncExecute = asyncExecute;
    }

    public void post(CtRemoteBusiness ctRemoteBusiness, ParseType parseType) {
        if (asyncExecute) {
            postAsync(ctRemoteBusiness, parseType);
        } else {
            postSync(ctRemoteBusiness, parseType);
        }
    }

    public Call postAsync(final CtRemoteBusiness ctRemoteBusiness, ParseType parseType) {
        Request request = buildRequest(ctRemoteBusiness);
        if (request == null) {
            return null;
        }
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new ResultCallback(parseType) {
            @Override
            public void onResponse(CtApiResponse ctApiResponse) {
                ApiProxyResult proxyResult = new ApiProxyResult();
                proxyResult.setType(APIPROXY_TYPE_RESPONSE);
                proxyResult.setData(ctApiResponse);
                if (BuildConfig.DEBUG) {
                    HttpLog httpLog = new HttpLog();
                    httpLog.setApiName(ctRemoteBusiness.request.getApiName());
                    httpLog.setRequest(ctRemoteBusiness.request.toAsJsonString());
                    httpLog.setCode(ctApiResponse.getCode());
                    httpLog.setResponse(ctApiResponse.getAsResponseString());
                    addLog(httpLog);
                }
                proxyResult.setmActionName(ctRemoteBusiness.request.getApiName());
                ctApiResponse.setApiName(ctRemoteBusiness.request.getApiName());
                setProxyResult(proxyResult, shouldResponseOnUiThread);
                AppLog.d("http method:" + ctRemoteBusiness.request.getApiName() + " , response:" + ctApiResponse.toString());
            }
        });
        return call;
    }

    private void addLog(HttpLog httpLog) {
        if (httpLogList.size() >= 10) {
            httpLogList.removeLast();
        }
        httpLogList.addFirst(httpLog);
    }

    public ApiProxyResult postSync(CtRemoteBusiness ctRemoteBusiness, ParseType parseType) {
        Request request = buildRequest(ctRemoteBusiness);
        ApiProxyResult proxyResult = new ApiProxyResult();
        if (request == null) {
            return proxyResult;
        }
        Call call = mOkHttpClient.newCall(request);
        try {
            Response response = call.execute();
            CtApiResponse ctApiResponse = new ResultCallback(parseType) {
                @Override
                public void onResponse(CtApiResponse ctApiResponse) {

                }
            }.handleResponse(response);
            proxyResult.setType(APIPROXY_TYPE_RESPONSE);
            proxyResult.setData(ctApiResponse);
            proxyResult.setmActionName(ctRemoteBusiness.request.getApiName());
            ctApiResponse.setApiName(ctRemoteBusiness.request.getApiName());
            setProxyResult(proxyResult, false);
            AppLog.d("http method:" + ctRemoteBusiness.request.getApiName() + " , response:" + ctApiResponse.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return proxyResult;
    }

    private Request buildRequest(CtRemoteBusiness ctRemoteBusiness) {
        if (ctRemoteBusiness == null) {
            return null;
        }
        CtApiRequest ctApiRequest = ctRemoteBusiness.request;
        String asJsonString = ctApiRequest.toAsJsonString();
        RequestBody requestBody = RequestBody.create(JSON, asJsonString);
        Request.Builder requestBuilder = new Request.Builder()
                .url(BusinessHelper.getApiUrl(ctRemoteBusiness.request.getApiName()))
                .post(requestBody);

        CacheControl cacheControl = null;
        if (CachePolicyEnum.RequestIgnoreCache
                .equals(ctRemoteBusiness.ctRequestProp.getCacheModel())) {
            cacheControl = CacheControl.FORCE_NETWORK;
        } else if (CachePolicyEnum.RequestUseCacheWhenExpireReload.equals(ctRemoteBusiness.ctRequestProp.getCacheModel())) {
            int defaultCacheTime = ctRemoteBusiness.ctRequestProp.getCustomerCacheTime();
            if (defaultCacheTime == 0) {
                defaultCacheTime = 60 * 60;
            }
            requestBuilder.header("Cache-Control", "public, max-age=" + defaultCacheTime);
           /* cacheControl = new CacheControl.Builder().onlyIfCached()
                    .maxAge(defaultCacheTime, TimeUnit.SECONDS).build();*/
        }

        if (cacheControl != null) {
            requestBuilder.cacheControl(cacheControl);
        }
        Request request = requestBuilder.build();

        AppLog.d("http method:" + ctApiRequest.getApiName() + " , request:" + asJsonString);
        return request;
    }

    public class ApiProxyResult extends ProxyResult {

        public ApiProxyResult() {
            setProxy(ApiProxy.class);
            setProxyName(ApiProxy.PROXY_NAME);
        }
    }


}
